const $dataIntegration = require("w-vue-chongqing/src/api/dataIntegration");
const setTableJoin = require("../setTableJoin").default;
const setTableMapping = require("../setTableMapping").default;
const setSqlJoin = require("../setSqlJoin").default;
const jobDebug = require("../jobDebug").default;
const $config = require("../config");

export default {
  components: {
    setTableJoin,
    setSqlJoin,
    setTableMapping,
    jobDebug
  },
  props: {
    value: {
      type: Array,
      default: () => {
        return [];
      }
    },
    modelInfo: {
      type: Object,
      default: () => {
        return {};
      }
    },
    jobInfo: {
      type: Object,
      default: () => {
        return {};
      }
    },
    targetColumns: {
      type: Array,
      default: () => {
        return [];
      }
    }
  },
  data() {
    return {
      loading: false,
      transferJobList: this.value,
      activeId: undefined,
      activeTransfer: {},
      tableCells: [],
      joinTable: {}, // 库表关联
      sqlTable: {}, //脚本输入
      outputTable: {}, //库表输出
      sourceColumns: [],
      tableColumns: {},
      debugInfo: {
        show: false,
        info: {}
      }
    };
  },
  watch: {
    value(val) {
      this.transferJobList = val;
      this.initData();
    },
    transferJobList(val) {
      this.$emit("input", val);
    }
  },
  created() {
    this.initData();
  },
  methods: {
    async initData() {
      if (this.transferJobList.length == 0) {
        // 初始化转换数据
        let transferData = $config.initTransferData(
          this.modelInfo,
          this.targetColumns
        );
        let { data: newId } = await $dataIntegration.getTransferNewId();
        this.transferJobList = []; // 调用id接口导致延迟；处理transferJobList默认变成两条数据的问题
        this.transferJobList.push({
          ...transferData,
          id: newId,
          jsonCells: JSON.parse(transferData.jsonDetail)
        });
        // 初始化jobInfo
        let { data: jobId } = await $dataIntegration.getTransferNewId();
        this.jobInfo.id = jobId;
        this.jobInfo.jobType = "job";
        this.jobInfo.parentId = null;
      } else {
        this.transferJobList.forEach(item => {
          let time = new Date().getTime();
          let random = Math.floor(Math.random() * 10000);
          let cells = JSON.parse(item.jsonDetail);
          let inputTables = cells.steps.filter(
            item => item.data.type === "TableInput"
          );
          let joinTable = cells.steps.find(
            item => item.data.type === "TableJoin"
          );
          let sqlTable = cells.steps.find(
            item => item.data.type === "SqlInput"
          );

          let joinInfo = JSON.DeepCopy($config.joinTableCell);
          joinInfo.data.id = `join_table_${random}_${time}`;
          // 编辑获取数据, 转换类型兼容处理
          if (!sqlTable) {
            item.mappingType = "join";
            let sqlInfo = JSON.DeepCopy($config.sqlTableCell);
            sqlInfo.data.id = `sql_table_${random}_${time}`;
            cells.steps.push({ ...sqlInfo });
            if (!joinTable) {
              cells.steps.push({ ...joinInfo });
            }
          }

          if (inputTables.length == 0) {
            item.mappingType = "sql";
            let inputInfo = JSON.DeepCopy($config.inputTableCell);
            inputInfo.data.id = `input_table_${random}_${time}`;
            cells.steps.push({ ...inputInfo });
            cells.steps.push({ ...joinInfo });
          }
          if (!item.jsonCells) {
            item.jsonCells = { ...cells };
          }
        });
      }

      let curItem = this.transferJobList.find(item => {
        return item.id == this.activeId;
      });
      if (!curItem && this.transferJobList.length) {
        this.activeTransfer = this.transferJobList[0];
        this.activeId = this.activeTransfer.id;
        this.getTransferData();
      }
    },
    /**
     * @Author: y_zp
     * @description: 数据校验
     */
    toValidate(callback) {
      for(let i = 0; i < this.transferJobList.length; i++) {
        let transfer = this.transferJobList[i];
        let tableMsg = "";
        let sqlMsg = "";
        let mapMsg = "";
        let cells = transfer.jsonCells.steps;
        if (transfer.mappingType == "join") {
          tableMsg = this.toValidateJoin(cells);
        } else {
          sqlMsg = this.toValidateSql(cells);
        }
        mapMsg = this.toValidateMapping(cells);

        if (tableMsg || sqlMsg || mapMsg) {
          this.$message.error(tableMsg || sqlMsg || mapMsg);
          this.activeId = transfer.id;
          this.changeTabs();
          return false;
        }
      }

      callback(true);
    },
    
    /**
     * @Author: y_zp
     * @description: 数据校验后获取数据
     */
    toValidateData(columnList = []) {
      let transferParams = [];
      // 作业json处理
      this.jobInfo.jsonDetail = JSON.stringify(this.getJobJson());
      // 转换json处理
      transferParams = this.transferJobList.map(transfer => {
        return {
          ...transfer,
          parentId: this.jobInfo.id,
          jsonDetail: JSON.stringify(this.getTransferJson(transfer, columnList)),
          jsonCells: undefined,
          mappingType: undefined
        };
      });

      return {
        ...this.jobInfo,
        transferJobs: transferParams
      }
    },

    /**
     * @Author: y_zp
     * @description: 校验关联表和关联条件
     */
    toValidateJoin(cells) {
      let msg = "";
      let inputTable = cells.filter(item => {
        return item.data.type == "TableInput";
      });
      let joinTable = cells.find(item => {
        return item.data.type == "TableJoin";
      });

      let tableNoData = inputTable.find(v => {
        return !v.data.dbId || !v.data.tableCode;
      });
      if (tableNoData) {
        msg = "请完善关联表";
        return msg;
      }

      // let whereString = inputTable.find(v => {
      //   return v.data.whereString;
      // })
      // if (!whereString) {
      //   msg = "请设置增量字段";
      //   return msg;
      // }

      for (let i = 0; i < joinTable.data.joins.length; i++) {
        let curItem = joinTable.data.joins[i];
        if (!curItem.right.asName) {
          msg = "请完善关联条件";
          return msg;
        }
        let curCondition = curItem.conditions.find(v => {
          return (
            (v.type == "sql" && !v.script) ||
            (v.type != "sql" &&
              (v.leftmap.length == 0 || v.rightmap.length == 0))
          );
        });
        if (curCondition) {
          msg = "请完善关联条件";
          return msg;
        }
      }
      return msg;
    },
    /**
     * @Author: y_zp
     * @description: 校验映射设置
     */
    toValidateMapping(cells) {
      let msg = "";
      let outputTable = cells.find(item => {
        return item.data.type == "TableOutput";
      });
      let isPk = false;
      let index = outputTable.data.mapping.filter(item => {
        if (item.target.pk) {
          isPk = true;
        }
        return item.target.notNull && !item.source.columnName;
      }).length;

      if (!isPk) {
        msg = $t("映射设置请至少设置一列为主键列");
        return msg;
      } else if (index > 0) {
        msg = $t("映射设置中存在非空列未设置输入列名信息");
        return msg;
      }
      return msg;
    },
    /**
     * @Author: y_zp
     * @description: 校验SQL
     */
    toValidateSql(cells) {
      let msg = "";
      let sqlTable = cells.find(item => {
        return item.data.type == "SqlInput";
      });
      if (!sqlTable.data.dbId || !sqlTable.data.script) {
        msg = "请完善脚本设置";
        return msg;
      }
      return msg;
    },

    /**
     * @Author: y_zp
     * @description: 添加转换
     */
    async toAddTransfer() {
      this.loading = true;
      let { data: newId } = await $dataIntegration.getTransferNewId();
      let columnList = this.targetColumns.map(v => {
        let desc = v.columnName;
        let name = v.columnCode;
        return {
          ...v,
          description: desc,
          columnName: name
        }
      })
      let transferData = $config.initTransferData(
        this.modelInfo,
        columnList
      );
      this.transferJobList.push({
        ...transferData,
        id: newId,
        jsonCells: JSON.parse(transferData.jsonDetail)
      });
      this.activeId = newId;
      this.changeTabs();
      this.loading = false;
    },
    /**
     * @Author: y_zp
     * @description: 删除转换
     */
    toDelTransfer(i) {
      let curTransfer = this.transferJobList[i];
      if (curTransfer.id == this.activeId) {
        this.activeId = this.transferJobList[i - 1].id;
        this.changeTabs();
      }
      this.transferJobList.splice(i, 1);
    },

    /**
     * @Author: y_zp
     * @description: 切换转换
     */
    changeTabs() {
      this.$nextTick(() => {
        let curT = this.transferJobList.find(item => item.id == this.activeId);
        this.activeTransfer = curT;
        this.getTransferData();
      });
    },
    /**
     * @Author: y_zp
     * @description: 初始化转换数据
     */
    getTransferData(type = "") {
      this.tableCells = this.activeTransfer.jsonCells.steps;
      this.joinTable = this.tableCells.find(
        item => item.data.type == "TableJoin"
      );
      this.sqlTable = this.tableCells.find(
        item => item.data.type == "SqlInput"
      );
      this.outputTable = this.tableCells.find(
        item => item.data.type == "TableOutput"
      );
      this.changeType(this.activeTransfer, type);
    },
    /**
     * @Author: y_zp
     * @description: 切换转换类型
     */
    changeType(item, type = "") {
      if (item.mappingType == "join") {
        this.changeTable(type);
      } else {
        this.changeSql();
      }
    },
    /**
     * @Author: y_zp
     * @description: 刷新数据
     */
    changeTableInfo() {
      let curT = this.transferJobList.find(item => item.id == this.activeId);
      this.activeTransfer = curT;
      this.getTransferData("auto");
    },
    /**
     * @Author: y_zp
     * @description: 切换输入表, type为auto时，自动关联映射
     */
    changeTable(type) {
      this.tableColumns = {};
      this.sourceColumns = [];
      let inputTable = this.tableCells.filter(
        item => item.data.type == "TableInput"
      );
      inputTable.forEach(table => {
        let item = table.data;

        if (item.tableCode && !this.tableColumns[item.tableCode]) {
          this.tableColumns[item.tableCode] = [];
        }

        item.columns.forEach(v => {
          this.tableColumns[item.tableCode].push(v.columnName);
          this.sourceColumns.push({
            ...v,
            id: `${item.asName}.${v.columnName}`,
            parentId: item.asName,
            tableCode: item.tableCode,
            tableId: item.tableId,
            tableAsName: item.asName || item.tableCode,
            tableName: item.tableName,
            asName: v.columnName
          });
        });
      });
      this.setDefaultMapping(type);
    },
    /**
     * @Author: y_zp
     * @description: 切换sql
     */
    changeSql(type) {
      this.tableColumns = {};
      this.sourceColumns = [];

      let item = this.sqlTable.data;
      this.tableColumns[item.tableCode] = [];
      item.columns.forEach(v => {
        this.tableColumns[item.tableCode].push(v.columnName);
        this.sourceColumns.push({
          ...v,
          id: `${item.asName}.${v.columnName}`,
          parentId: item.asName,
          tableCode: item.tableCode,
          tableId: item.tableId,
          tableAsName: item.asName || item.tableCode,
          tableName: item.tableName,
          asName: v.columnName
        });
      });
      this.setDefaultMapping(type);
    },
    /**
     * @Author: y_zp
     * @description: 设置默认mapping信息，type为auto时，自动关联
     */
    setDefaultMapping(type = "") {
      let mapping = this.outputTable.data.mapping;
      this.outputTable.data.mapping = this.outputTable.data.columns.map(
        column => {
          let original = mapping.find(v => {
            if (v.target && v.target.columnName) {
              if (v.target.tableAsName) {
                return (
                  v.target.columnName.toLocaleLowerCase() ==
                    column.columnName.toLocaleLowerCase() &&
                  v.target.tableAsName.toLocaleLowerCase() ==
                    column.tableAsName.toLocaleLowerCase()
                );
              } else {
                return (
                  v.target.columnName.toLocaleLowerCase() ==
                  column.columnName.toLocaleLowerCase()
                );
              }
            } else {
              return false;
            }
          });

          let source = {
            pk: false,
            columnName: undefined,
            select: undefined,
            type: "fun",
            columnType: undefined,
            description: undefined,
            columnTypeFlink: undefined,
            lockType: false
          };
          if (original) {
            source = {
              ...source,
              ...original.source
            };
          }
          return {
            target: {
              ...column
            },
            source: {
              ...source
            }
          };
        }
      );
      this.$nextTick(() => {
        if (
          this.$refs[`tableMapping_${this.activeId}`] &&
          this.$refs[`tableMapping_${this.activeId}`][0]
        ) {
          this.$refs[`tableMapping_${this.activeId}`][0].initData(type);
        }
      });
    },
    /**
     * @Author: y_zp
     * @description: 作业调试
     */
    toDebug() {
      this.debugInfo = {
        show: true,
        info: {}
      };
    },
    /**
     * @Author: y_zp
     * @description: 设置增量字段
     */
    changeIncField(value) {
      this.tableCells.forEach(item => {
        if(item.data.type == 'TableInput') {
          if(item.data.tableCode == value.tableCode && item.data.asName == value.tableAsName) {
            item.data.whereString = (value.select || value.columnName) + " BETWEEN ${lowerbound} and ${upperbound}";
          } else {
            item.data.whereString = "";
          }
        }
      })
    },

    /**
     * @Author: y_zp
     * @description: 获取作业的json
     */
    getJobJson() {
      let time = new Date().getTime();
      let random = Math.floor(Math.random() * 10000);

      let startRightPort = {
        group: "right",
        id: `start_right_port_${time}`
      };

      let startNode = {
        ...JSON.DeepCopy($config.startNodeJson),
        id: `start_${random}_${time}`,
        ports: {
          items: [
            {
              group: "top",
              id: `start_top_port_${time}`
            },
            {
              group: "left",
              id: `start_left_port_${time}`
            },
            startRightPort,
            {
              group: "bottom",
              id: `start_bottom_port_${time}`
            }
          ]
        }
      };
      let endLeftPort = {
        group: "left",
        id: `end_left_port_${time}`
      };
      let endNode = {
        ...JSON.DeepCopy($config.endNodeJson),
        id: `end_${random}_${time}`,
        ports: {
          items: [
            {
              group: "top",
              id: `end_top_port_${time}`
            },
            endLeftPort,
            {
              group: "right",
              id: `end_right_port_${time}`
            },
            {
              group: "bottom",
              id: `end_bottom_port_${time}`
            }
          ]
        }
      };

      let hops = [];
      let transferNode = this.transferJobList.map((node, index) => {
        let tRandom = Math.floor(Math.random() * 10000);
        let leftPort = {
          group: "left",
          id: `transfer_left_port_${tRandom}_${time}`
        };
        let rightPort = {
          group: "right",
          id: `transfer_right_port_${tRandom}_${time}`
        };

        let nodeData = {
          data: {
            id: `transfer_${tRandom}_${time}`,
            name: node.jobName,
            type: "SubTransform",
            code: `SubTransform_${$storage.userInfo.userId}_${tRandom}_${time}`,
            jobId: node.id,
            jobName: node.jobName,
            steps: [],
            hops: []
          },
          id: `transfer_table_${tRandom}_${time}`,
          label: "转换",
          shape: "custom-input",
          position: { x: 200, y: 150 + index * 60 },
          size: { width: 160, height: 36 },
          view: "vue-shape-view",
          zIndex: 1,
          ports: {
            items: [
              {
                group: "top",
                id: `transfer_top_port_${tRandom}_${time}`
              },
              leftPort,
              rightPort,
              {
                group: "bottom",
                id: `transfer_bottom_port_${tRandom}_${time}`
              }
            ]
          }
        };
        // 左边和开始的连线
        hops.push({
          id: `link_hops_left_${tRandom}_${time}`,
          shape: "edge",
          source: {
            cell: startNode.id,
            port: startRightPort.id
          },
          target: {
            cell: nodeData.id,
            port: leftPort.id
          },
          ...$config.lineoption
        });
        // 右边和结束的连线
        hops.push({
          id: `link_hops_right_${tRandom}_${time}`,
          shape: "edge",
          source: {
            cell: nodeData.id,
            port: rightPort.id
          },
          target: {
            cell: endNode.id,
            port: endLeftPort.id
          },
          ...$config.lineoption
        });

        return nodeData;
      });

      return {
        ver: "2.02",
        steps: [startNode, ...transferNode, endNode],
        hops
      };
    },

    /**
     * @Author: y_zp
     * @description: 获取转换的json
     */
    getTransferJson(transfer, newColumnList) {
      let time = new Date().getTime();
      let random = Math.floor(Math.random() * 10000);

      let cells = transfer.jsonCells.steps;
      let inputTables = cells.filter(item => {
        return item.data.type == "TableInput";
      });
      let joinTable = cells.find(item => {
        return item.data.type == "TableJoin";
      });
      let sqlTable = cells.find(item => {
        return item.data.type == "SqlInput";
      });
      let optputTable = cells.find(item => {
        return item.data.type == "TableOutput";
      });
      // 同步optputTable字段
      if(newColumnList && newColumnList.length) {
        optputTable.data.tableCode = this.modelInfo.tableCode.toLocaleLowerCase();
        optputTable.data.tableName = this.modelInfo.tableName;

        optputTable.data.columns = newColumnList;
        let tempMapping = JSON.DeepCopy(optputTable.data.mapping);
        optputTable.data.mapping = tempMapping.map(v => {
          let newT = newColumnList.find(c => { return v.target.columnName.toLocaleLowerCase() == c.columnName.toLocaleLowerCase() });
          let isPk = v.target.pk;
          let isComplete = v.target.isComplete;
          return {
            source: { ...v.source },
            target: {
              ...v.target,
              ...newT,
              pk: isPk,
              isComplete: isComplete
            }
          }
        })
      }

      let outputLeftPort = {
        group: "left",
        id: `output_left_port_${random}_${time}`
      };
      let outputNode = {
        ...JSON.DeepCopy(optputTable),
        id: `output_${random}_${time}`,
        position: { x: 700, y: 200 },
        ports: {
          items: [
            {
              group: "top",
              id: `output_top_port_${random}_${time}`
            },
            {
              group: "right",
              id: `output_right_port_${random}_${time}`
            },
            outputLeftPort,
            {
              group: "bottom",
              id: `output_bottom_port_${random}_${time}`
            }
          ]
        }
      };

      let joinLeftPort = {
        group: "left",
        id: `join_left_port_${random}_${time}`
      };
      let joinRightPort = {
        group: "right",
        id: `join_right_port_${random}_${time}`
      };
      let joinNode = {
        ...JSON.DeepCopy(joinTable),
        id: `join_${random}_${time}`,
        position: { x: 500, y: 200 },
        ports: {
          items: [
            {
              group: "top",
              id: `join_top_port_${random}_${time}`
            },
            joinLeftPort,
            joinRightPort,
            {
              group: "bottom",
              id: `join_bottom_port_${random}_${time}`
            }
          ]
        }
      };

      let hops = [];
      if (transfer.mappingType == "join") {
        let inputNodes = inputTables.map((node, index) => {
          let iRandom = Math.floor(Math.random() * 10000);
          let rightPort = {
            group: "right",
            id: `input_right_port_${iRandom}_${time}`
          };

          let nodeData = {
            ...JSON.DeepCopy(node),
            id: `input_${iRandom}_${time}`,
            position: { x: 100, y: 200 + index * 60 },
            ports: {
              items: [
                {
                  group: "top",
                  id: `input_top_port_${iRandom}_${time}`
                },
                {
                  group: "left",
                  id: `input_left_port_${iRandom}_${time}`
                },
                rightPort,
                {
                  group: "bottom",
                  id: `input_bottom_port_${iRandom}_${time}`
                }
              ]
            }
          };
          // 只有一张来源表表
          if (inputTables.length == 1) {
            hops.push({
              id: `link_hops_input_${iRandom}_${time}`,
              shape: "edge",
              source: {
                cell: nodeData.id,
                port: rightPort.id
              },
              target: {
                cell: outputNode.id,
                port: outputLeftPort.id
              },
              ...$config.lineoption
            });
          } else {
            // 多个输入表
            hops.push({
              id: `link_hops_input_${iRandom}_${time}`,
              shape: "edge",
              source: {
                cell: nodeData.id,
                port: rightPort.id
              },
              target: {
                cell: joinNode.id,
                port: joinLeftPort.id
              },
              ...$config.lineoption
            });
          }
          return nodeData;
        });
        if (inputTables.length > 1) {
          hops.push({
            id: `link_hops_join_${random}_${time}`,
            shape: "edge",
            source: {
              cell: joinNode.id,
              port: joinRightPort.id
            },
            target: {
              cell: outputNode.id,
              port: outputLeftPort.id
            },
            ...$config.lineoption
          });
        }
        return {
          ver: "2.02",
          steps:
            inputTables.length > 1
              ? [...inputNodes, joinNode, outputNode]
              : [...inputNodes, outputNode],
          hops
        };
      } else {
        let sqlRightPort = {
          group: "right",
          id: `sql_right_port_${random}_${time}`
        };

        let sqlNode = {
          ...JSON.DeepCopy(sqlTable),
          id: `sql_${random}_${time}`,
          position: { x: 200, y: 200 },
          ports: {
            items: [
              {
                group: "top",
                id: `sql_top_port_${random}_${time}`
              },
              {
                group: "left",
                id: `sql_left_port_${random}_${time}`
              },
              sqlRightPort,
              {
                group: "bottom",
                id: `sql_bottom_port_${random}_${time}`
              }
            ]
          }
        };
        hops.push({
          id: `link_hops_join_${random}_${time}`,
          shape: "edge",
          source: {
            cell: sqlNode.id,
            port: sqlRightPort.id
          },
          target: {
            cell: outputNode.id,
            port: outputLeftPort.id
          },
          ...$config.lineoption
        });

        return {
          ver: "2.02",
          steps: [sqlNode, outputNode],
          hops
        };
      }
    }
  }
};
